home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / fpkpas92.zip / SRCRTL.ZIP / RTL / DOS / CRT.PP < prev    next >
Text File  |  1997-07-01  |  16KB  |  670 lines

  1. {****************************************************************************
  2.  
  3.                         FPKPascal run time library
  4.                          Copyright (c) 1993,96 by
  5.                      Florian Klaempfl & Michael Spiegel
  6.  
  7.  ****************************************************************************}
  8.  
  9. {
  10.   history:
  11.   29th may 1994: version 1.0
  12.              unit is completed
  13.   14th june 1994: version 1.01
  14.              the address from which startaddr was read wasn't right; fixed
  15.   18th august 1994: version 1.1
  16.              the upper left corner of winmin is now 0,0
  17.   19th september 1994: version 1.11
  18.              keypressed handles extended keycodes false; fixed
  19.   27th february 1995: version 1.12
  20.              * crtinoutfunc didn't the line wrap in the right way;
  21.                fixed
  22.   20th january 1996: version 1.13
  23.              - unused variables removed
  24.   21th august 1996: version 1.14
  25.              * adapted to newer FPKPascal versions
  26.              * make the comments english
  27.    6th november 1996: version 1.49
  28.              * some stuff for DPMI adapted
  29.   15th november 1996: version 1.5
  30.              * bug in screenrows fixed
  31. }
  32.  
  33. unit crt;
  34.  
  35.   interface
  36.   
  37.     uses
  38.        go32;
  39.  
  40.     const
  41.        { screen modes }
  42.        bw40 = 0;
  43.        co40 = 1;
  44.        bw80 = 2;
  45.        co80 = 3;
  46.        mono = 7;
  47.        font8x8 = 256;
  48.  
  49.        { screen color, fore- and background }
  50.        black = 0;
  51.        blue = 1;
  52.        green = 2;
  53.        cyan = 3;
  54.        red = 4;
  55.        magenta = 5;
  56.        brown = 6;
  57.        lightgray = 7;
  58.  
  59.        { only foreground }
  60.        darkgray = 8;
  61.        lightblue = 9;
  62.        lightgreen = 10;
  63.        lightcyan = 11;
  64.        lightred = 12;
  65.        lightmagenta = 13;
  66.        yellow = 14;
  67.        white = 15;
  68.  
  69.        { blink flag }
  70.        blink = $80;
  71.  
  72.     var
  73.        { for compatibility }
  74.        checkbreak,checkeof,checksnow : boolean;
  75.  
  76.        { works in another way than in TP }
  77.        { true: cursor is set with direct port access }
  78.        { false: cursor is set with a bios call       }
  79.        directvideo : boolean;
  80.  
  81.        lastmode : word; { screen mode}
  82.        textattr : byte; { current text attribute }
  83.        windmin : word; { upper right corner of the CRT window }
  84.        windmax : word; { lower left corner of the CRT window }
  85.  
  86.     function keypressed : boolean;
  87.     function readkey : char;
  88.     procedure gotoxy(x,y : byte);
  89.     procedure window(left,top,right,bottom : byte);
  90.     procedure clrscr;
  91.     procedure textcolor(color : byte);
  92.     procedure textbackground(color : byte);
  93.     procedure assigncrt(var f : text);
  94.     function wherex : byte;
  95.     function wherey : byte;
  96.     procedure delline;
  97.     procedure delline(line : byte);
  98.     procedure clreol;
  99.     procedure insline;
  100.     procedure cursoron;
  101.     procedure cursoroff;
  102.     procedure cursorbig;
  103.     procedure lowvideo;
  104.     procedure highvideo;
  105.     procedure nosound;
  106.     procedure sound(hz : word);
  107.     procedure delay(ms : longint);
  108.     procedure textmode(mode : integer);
  109.     procedure normvideo;
  110.     
  111.   implementation
  112.   
  113.     var
  114.        maxcols,maxrows : longint;
  115.   
  116.     type
  117.        pword = ^word;
  118.         
  119.        textbuf = array[0..127] of char;
  120.  
  121.        textrec = record
  122.           handle : word;
  123.           mode : word;
  124.           bufSize : word;
  125.           { private : word; PRIVATE is keyword of FPKPascal }
  126.           _private : word;
  127.           bufpos : word;
  128.           bufend : word;
  129.           bufptr : ^textbuf;
  130.           openfunc : pointer;
  131.           inoutfunc : pointer;
  132.           flushfunc : pointer;
  133.           closefunc : pointer;
  134.           userdata : array[1..16] of byte;
  135.           name : string[79];
  136.           buffer : textbuf;
  137.        end;
  138.        
  139.     { includes low level routines }
  140.  
  141.     {$i modes.inc}
  142.  
  143.     function screenrows : byte;
  144.  
  145.       begin
  146.          dosmemget($40,$84,screenrows,1);
  147.          { don't forget this: }
  148.          inc(screenrows);
  149.       end;
  150.  
  151.     function screencols : byte;
  152.  
  153.       begin
  154.          dosmemget($40,$4a,screencols,1);
  155.       end;
  156.       
  157.     function get_addr(row,col : byte) : word;
  158.     
  159.       begin
  160.          get_addr:=((row-1)*maxcols+(col-1))*2;
  161.       end;
  162.  
  163.     procedure screensetcursor(row,col : longint);
  164.  
  165.       var
  166.          cols : byte;
  167.          pos : word;
  168.  
  169.       begin
  170.          if directvideo then
  171.            begin
  172.               { set new position for the BIOS }
  173.               dosmemput($40,$51,row,1);
  174.               dosmemput($40,$50,col,1);
  175.  
  176.               { calculates screen position }
  177.               dosmemget($40,$4a,cols,1);              
  178.               { FPKPascal calculates with 32 bit }
  179.               pos:=row*cols+col;
  180.  
  181.               { direct access to the graphics card registers }
  182.               outportb($3d4,$0e);
  183.               outportb($3d5,hi(pos)); 
  184.               outportb($3d4,$0f);
  185.               outportb($3d5,lo(pos)); 
  186.            end
  187.          else
  188.             asm
  189.                movb     $0x02,%ah
  190.                movb     $0,%bh
  191.                movb     row,%dh
  192.                movb     col,%dl
  193.                pushl    %ebp
  194.                int      $0x10
  195.                popl     %ebp
  196.             end;
  197.        end;
  198.  
  199.     procedure screengetcursor(var row,col : longint);
  200.  
  201.       begin
  202.          col:=0;
  203.          row:=0;
  204.          dosmemget($40,$50,col,1);
  205.          dosmemget($40,$51,row,1);
  206.       end;
  207.  
  208.     { exported routines }
  209.  
  210.     procedure cursoron;
  211.  
  212.       begin
  213.          asm
  214.             movb   $1,%ah
  215.             movb   $10,%cl
  216.             movb   $9,%ch
  217.             pushl %ebp
  218.             int   $0x10
  219.             popl %ebp
  220.          end;
  221.       end;
  222.    
  223.     procedure cursoroff;
  224.     
  225.       begin
  226.          asm
  227.             movb   $1,%ah
  228.             movb   $-1,%cl
  229.             movb   $-1,%ch
  230.             pushl %ebp
  231.             int   $0x10
  232.             popl %ebp
  233.          end;
  234.       end;
  235.    
  236.     procedure cursorbig;
  237.    
  238.       begin
  239.          asm
  240.             movb   $1,%ah
  241.             movb   $10,%cl
  242.             movb   $1,%ch
  243.             pushl %ebp
  244.             int   $0x10
  245.             popl %ebp
  246.          end;
  247.       end;
  248.       
  249.     var
  250.        is_last : boolean;
  251.        last : char;
  252.  
  253.     function readkey : char;
  254.  
  255.       var
  256.          char2 : char;
  257.          char1 : char;
  258.  
  259.       begin
  260.          if is_last then
  261.            begin
  262.               is_last:=false;
  263.               readkey:=last;
  264.            end
  265.          else
  266.            begin
  267.               asm
  268.                  movb $0,%ah
  269.                  pushl %ebp
  270.                  int $0x16
  271.                  popl %ebp
  272.                  movw %ax,-2(%ebp)
  273.               end;
  274.               if char1=#0 then
  275.                 begin
  276.                    is_last:=true;
  277.                    last:=char2;
  278.                 end;
  279.               readkey:=char1;
  280.            end;
  281.       end;
  282.  
  283.     function keypressed : boolean;
  284.  
  285.       begin
  286.          if is_last then
  287.            begin
  288.               keypressed:=true;
  289.               exit;
  290.            end
  291.          else
  292.            asm
  293.               movb $1,%ah
  294.               pushl %ebp
  295.               int $0x16
  296.               popl %ebp
  297.               setnz %al
  298.               movb %al,__RESULT
  299.            end;
  300.       end;
  301.  
  302.    procedure gotoxy(x,y : byte);
  303.  
  304.      begin
  305.         if (x<1) then
  306.           x:=1;
  307.         if (y<1) then
  308.           y:=1;
  309.         if y+hi(windmin)-2>=hi(windmax) then
  310.           y:=hi(windmax)-hi(windmin)+1;
  311.         if x+lo(windmin)-2>=lo(windmax) then
  312.           x:=lo(windmax)-lo(windmin)+1;
  313.         screensetcursor(y+hi(windmin)-1,x+lo(windmin)-1);
  314.      end;
  315.  
  316.    function wherex : byte;
  317.  
  318.      var
  319.         row,col : longint;
  320.  
  321.      begin
  322.         screengetcursor(row,col);
  323.         wherex:=col-lo(windmin)+1;
  324.      end;
  325.  
  326.    function wherey : byte;
  327.  
  328.      var
  329.         row,col : longint;
  330.  
  331.      begin
  332.         screengetcursor(row,col);
  333.         wherey:=row-hi(windmin)+1;
  334.      end;
  335.  
  336.    procedure window(left,top,right,bottom : byte);
  337.  
  338.      begin
  339.         if (left<1) or
  340.            (right>screencols) or
  341.            (bottom>screenrows) or
  342.            (left>right) or
  343.            (top>bottom) then
  344.            exit;
  345.         windmin:=(left-1) or ((top-1) shl 8);
  346.         windmax:=(right-1) or ((bottom-1) shl 8);
  347.         gotoxy(1,1);
  348.      end;
  349.  
  350.    procedure clrscr;
  351.  
  352.      var
  353.         fil : word;
  354.         row : longint;
  355.  
  356.      begin
  357.         fil:=32 or (textattr shl 8);
  358.         for row:=hi(windmin) to hi(windmax) do
  359.           dosmemfillword($b800,get_addr(row+1,lo(windmin)+1),lo(windmax)-lo(windmin)+1,fil);
  360.         gotoxy(1,1);
  361.      end;
  362.  
  363.    procedure textcolor(color : Byte);
  364.  
  365.      begin
  366.         textattr:=(textattr and $70) or color;
  367.      end;
  368.  
  369.    procedure lowvideo;
  370.  
  371.      begin
  372.         textattr:=textattr and $f7;
  373.      end;
  374.  
  375.    procedure highvideo;
  376.  
  377.      begin
  378.         textattr:=textattr or $08;
  379.      end;
  380.  
  381.    procedure textbackground(color : Byte);
  382.  
  383.      begin
  384.         textattr:=(textattr and $8f) or ((color and $7) shl 4);
  385.      end;
  386.  
  387.    var
  388.       startattrib : byte;
  389.  
  390.    procedure normvideo;
  391.  
  392.      begin
  393.         textattr:=startattrib;
  394.      end;
  395.  
  396.    procedure delline(line : byte);
  397.  
  398.      var
  399.         row,left,right,bot : longint;
  400.         fil : word;
  401.  
  402.      begin
  403.         row:=line+hi(windmin);
  404.         left:=lo(windmin)+1;
  405.         right:=lo(windmax)+1;
  406.         bot:=hi(windmax)+1;
  407.         fil:=32 or (textattr shl 8);
  408.         while (row<bot) do
  409.           begin
  410.              dosmemmove($b800,get_addr(row+1,left),$b800,get_addr(row,left),(right-left+1)*2);
  411.              inc(row);
  412.           end;
  413.         dosmemfillword($b800,get_addr(bot,left),right-left+1,fil);
  414.      end;
  415.  
  416.    procedure delline;
  417.  
  418.      begin
  419.         delline(wherey);
  420.      end;
  421.  
  422.    procedure insline;
  423.  
  424.      var
  425.         row,col,left,right,bot : longint;
  426.         fil : word;
  427.  
  428.      begin
  429.         screengetcursor(row,col);
  430.         inc(row);
  431.         left:=lo(windmin)+1;
  432.         right:=lo(windmax)+1;
  433.         bot:=hi(windmax);
  434.         fil:=32 or (textattr shl 8);
  435.         while (bot>row) do
  436.           begin
  437.              dosmemmove($b800,get_addr(bot-1,left),$b800,get_addr(bot,left),(right-left+1)*2);
  438.              dec(bot);
  439.           end;
  440.         dosmemfillword($b800,get_addr(row,left),right-left+1,fil);
  441.      end;
  442.  
  443.    procedure clreol;
  444.  
  445.      var
  446.         row,col : longint;
  447.         fil : word;
  448.  
  449.      begin
  450.         screengetcursor(row,col);
  451.         inc(row);
  452.         inc(col);
  453.         fil:=32 or (textattr shl 8);
  454.         dosmemfillword($b800,get_addr(row,col),lo(windmax)-col+2,fil);
  455.      end;
  456.  
  457.    procedure crtinoutfunc(var f : textrec);
  458.  
  459.       var
  460.          i,col,row : longint;
  461.          c : char;
  462.          va,sa : word;
  463.  
  464.       begin
  465.          screengetcursor(row,col);
  466.          inc(row);
  467.          inc(col);
  468.          va:=get_addr(row,col);
  469.          if f.mode=fmoutput then
  470.            begin
  471.               for i:=0 to f.bufpos-1 do
  472.                 begin
  473.                    c:=f.buffer[i];
  474.                    case ord(c) of
  475.                       10 : begin
  476.                               inc(row);
  477.                               va:=va+maxcols*2;
  478.                            end;
  479.                       13 : begin
  480.                               col:=lo(windmin)+1;
  481.                               va:=get_addr(row,col);
  482.                           end;
  483.                       8 : if col>lo(windmin)+1 then
  484.                             begin
  485.                                dec(col);
  486.                                va:=va-2;
  487.                             end;
  488.                       7 : begin
  489.                               { beep }
  490.                            end;
  491.                    else
  492.                       begin
  493.                          sa:=textattr shl 8 or ord(c);
  494.                          dosmemput($b800,va,sa,sizeof(sa));
  495.                          inc(col);
  496.                          va:=va+2;
  497.                       end;
  498.                    end;
  499.                    if col>lo(windmax)+1 then
  500.                      begin
  501.                         col:=lo(windmin)+1;
  502.                         inc(row);
  503.  
  504.                         { it's easier to calculate the new address }
  505.                         { it don't spend much time                 }
  506.                         va:=get_addr(row,col);
  507.                      end;
  508.                    while row>hi(windmax)+1 do
  509.                      begin
  510.                         delline(1);
  511.                         dec(row);
  512.                         va:=va-maxcols*2;
  513.                      end;
  514.                 end;
  515.               f.bufpos:=0;
  516.               screensetcursor(row-1,col-1);
  517.            end
  518.          {!!!!!!}
  519.          else halt(100);
  520.       end;
  521.  
  522.    procedure assigncrt(var f : text);
  523.  
  524.      begin
  525.         textrec(f).inoutfunc:=@crtinoutfunc;
  526.         textrec(f).flushfunc:=@crtinoutfunc;
  527.      end;
  528.  
  529.    procedure sound(hz : word);
  530.  
  531.      begin
  532.         if hz=0 then
  533.           begin
  534.              nosound;
  535.              exit;
  536.           end;
  537.         asm
  538.            movzwl hz,%ecx
  539.            movl $1193046,%eax
  540.            cdql
  541.            divl %ecx
  542.            movl %eax,%ecx
  543.            movb $0xb6,%al
  544.            outb %al,$0x43
  545.            movb %cl,%al
  546.            outb %al,$0x42
  547.            movb %ch,%al
  548.            outb %al,$0x42
  549.            inb $0x61,%al
  550.            orb $0x3,%al
  551.            outb %al,$0x61
  552.         end ['EAX','ECX','EDX'];
  553.      end;
  554.  
  555.    procedure nosound;
  556.  
  557.      begin
  558.         asm
  559.            inb $0x61,%al
  560.            andb $0xfc,%al
  561.            outb %al,$0x61
  562.         end ['EAX'];
  563.      end;
  564.  
  565.    var
  566.       calibration : longint;
  567.  
  568.    procedure delay(ms : longint);
  569.  
  570.       var
  571.          i,j : longint;
  572.  
  573.      begin
  574.         for i:=1 to ms do
  575.           for j:=1 to calibration do
  576.              begin
  577.              end;
  578.      end;
  579.  
  580.   function get_ticks : word;
  581.  
  582.     begin
  583.        dosmemget($40,$6c,get_ticks,2);
  584.     end;
  585.  
  586.   procedure initdelay;
  587.  
  588.     var
  589.        first : word;
  590.  
  591.     begin
  592.        calibration:=0;
  593.  
  594.        { wait for new tick }
  595.        first:=get_ticks;
  596.        while get_ticks=first do
  597.          begin
  598.          end;
  599.        first:=get_ticks;
  600.  
  601.        { this estimates calibration }
  602.        while get_ticks=first do
  603.          inc(calibration);
  604.  
  605.        { calculate this to ms }
  606.        calibration:=calibration div 70;
  607.        while true do
  608.          begin
  609.             first:=get_ticks;
  610.             while get_ticks=first do
  611.               begin
  612.               end;
  613.             first:=get_ticks;
  614.             delay(55);
  615.             if first=get_ticks then
  616.                exit
  617.             else begin
  618.                     { decrement calibration two percent }
  619.                     calibration:=calibration-calibration div 50;
  620.                     dec(calibration);
  621.                  end;
  622.          end;
  623.     end;
  624.  
  625.   procedure textmode(mode : integer);
  626.  
  627.     var
  628.        set_font8x8 : boolean;
  629.  
  630.     begin
  631.        lastmode:=mode;
  632.        set_font8x8:=(mode and font8x8)<>0;
  633.        mode:=mode and $ff;
  634.        setscreenmode(mode);
  635.        windmin:=0;
  636.        windmax:=(screencols-1) or ((screenrows-1) shl 8);
  637.        maxcols:=screencols;
  638.        maxrows:=screenrows;
  639.     end;
  640.  
  641. var
  642.    col,row : longint;
  643.  
  644. begin
  645.    is_last:=false;
  646.  
  647.    { direct access to graphics card registers }
  648.    directvideo:=true;
  649.  
  650.    { set output window }
  651.    windmin:=0;
  652.    windmax:=(screencols-1) or ((screenrows-1) shl 8);
  653.  
  654.    { load system variables to temporary variables to save time }
  655.    maxcols:=screencols;
  656.    maxrows:=screenrows;
  657.  
  658.    { save the current settings to restore the old state after the exit }
  659.    screengetcursor(row,col);
  660.    dosmemget($b800,get_addr(row+1,col+1)+1,startattrib,1);
  661.    lastmode:=getscreenmode;
  662.    textattr:=startattrib;
  663.  
  664.    { redirect the standard output }
  665.    assigncrt(output);
  666.  
  667.    { calculates delay calibration }
  668.    initdelay;
  669. end.
  670.